JS异步解析

同步和异步

举个🌰,你给餐厅打电话,要查某个消费记录,这时候餐厅去查消费记录,你在电话那头等着,不能做其他事情,只有餐厅查到消费记录告诉你才能做其他事情。这个就是同步。

异步就是这样的:你还是去给餐厅打电话,还是要查某个消费记录,这时候餐厅还是去查消费记录,但是餐厅告诉你,你不用等,我们查到就会立马告诉你的,你可以去做其他事情了。

单线程

我们肯定需要知道,JS为什么需要异步,异步这玩意有什么用。

众所周知,JS是一门单线程的编程语言,也就是说JS同一时间只能做一件事情。JS之所以是单线程的编程语言,是为了避免DOM渲染冲突。

比如说有两段代码,一个代码是将div的背景颜色设为红色,另一个代码是将div的背景颜色设为蓝色,如果这两段代码同时进行,这不就冲突了么。只能同一时间运行一段代码,而不是多段代码。

单线程也意味着会发生上一段代码没有执行完毕,下一段代码就无法执行的情况,也就是阻塞。

为了提高运行效率, 异步便是单线程的解决方案。

同步代码示例

alert('我要查消费记录');

console.log('查到了');

在没有点击 alert 弹出的消息之前,“查到了”这条信息是不会出现在控制台的,只有点击 alert 的确定,才能执行console.log('查到了')

由此可见,同步会阻塞代码的执行。

异步代码示例

console.log('我要查询消费记录');

setTimeout(function () {
console.log('我查到了');
}, 1000);

console.log('做其他事情');

先输出我要查询记录,紧接着输出做其他事情,1s后输出我查到了

异步的好处就是不会阻塞代码的执行, 在输出我查到了这条信息之前,我是可以做其他事情的。

异步的机制

光是了解异步是什么,好处是啥,我认为这还是不够的。我们还需要了解异步的机制,以应对工作中的各种情况,在了解了异步机制后,碰到异步代码也会有不一样的感受。

先看一段代码再说:

// 主线程
console.log(100);

// 异步队列
setTimeout(function () {
console.log(200);
}, 100);

// 异步队列
setTimeout(function () {
console.log(300);
}, 0);

// 主线程
console.log(400);

// 这段代码输出的结果依次为:100,400,300,200

为什么会输出这样的结果呢?

  • 主线程代码先执行。

  • 同步代码,同步执行。

  • 异步函数先放到异步队列当中去。

  • 等同步代码执行完毕,再轮询执行异步队列中的函数。

解释一下这段代码执行过程:

console.log(100)先执行, 输出100, console.log(300)立即放入异步队列中去, 100ms后, console.log(200)放入异步队列中去。

执行console.log(400), 输出400, 同步代码执行完毕。轮询异步队列中的函数。先输出300, 再输出200;

异步的原理

王福鹏老师的异步解析

这段受王福鹏老师的启发,做补充。感兴趣的同学,可以去点击上面的连接,查看更详细的异步解析。

$.get('xxx.json', function (data, state) {
console.log(data);
});

这是 jQuery 发起 ajax 请求的一段代码,两个参数,一个 url 和一个 function(data, state), 这个function(data, state)不会立即执行,只有请求的数据拿到了,才会执行。

这里引用王福鹏老师的话: 实现异步的最核心原理,就是将callback作为参数传递给异步执行函数,当有结果返回之后再触发 callback执行

异步的使用场景

  • 定时任务: setTimeout, setInterval

  • 网络请求: ajax请求, 动态<img>加载

  • 事件绑定